package ${pPackage}.common.aop;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.UUID;

@Aspect
@Component
public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private static final ThreadLocal<Long> timeTreadLocal = new ThreadLocal<>();

    @Pointcut("execution(* ${pPackage}..controller.*.*(..))")
    public void logController() {
    }

    @Before("logController()")
    public void before(JoinPoint joinPoint) {
        timeTreadLocal.set(System.currentTimeMillis());
        String TRACE_ID = UUID.randomUUID().toString();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        String requestUrl = request.getServletPath() + (StringUtils.isBlank(request.getQueryString()) ? "" : "?" + request.getQueryString());
        request.setAttribute("TRACE_ID", TRACE_ID);
        try {
            logger.info("【traceId】= {},【请求方法】= {},【请求方式】= {},【请求地址】= {},【请求参数】= {}", TRACE_ID, method.getDeclaringClass() + "." + methodName + "()", request.getMethod(), requestUrl, JSONObject.toJSONString(joinPoint.getArgs()));
        } catch (Exception e) {
            logger.info("【traceId】= {},【请求方法】= {},【请求方式】= {},【请求地址】= {},【请求参数】= {}", TRACE_ID, method.getDeclaringClass() + "." + methodName + "()", request.getMethod(), requestUrl, "{}");

        }
    }

    @AfterReturning(pointcut = "logController()", returning = "result")
    public Object afterReturning(Object result) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String TRACE_ID = (String) request.getAttribute("TRACE_ID");
        long startTime = timeTreadLocal.get();
        double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
        logger.info("【traceId】= {},【请求耗时】= {}s,【result】= {}", TRACE_ID, callTime, JSONObject.toJSONString(result));
        return result;
    }

    @AfterThrowing("logController()")
    public void afterThrowing() {
        System.out.println("afterThrowing 在抛出异常时执行");
    }

}
